home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 033a / aed244a.zip / AED244.BAS next >
BASIC Source File  |  1991-02-16  |  46KB  |  1,427 lines

  1. '*
  2. '*  ANSIED v2.44a
  3. '*---------------------------------------------------------------------------
  4. '*  Full Screen Text Editor for RBBS-PC
  5. '*  QuickBASIC v4.5 Standalone Version
  6. '*  02-16-91
  7. '*
  8. '*  v2.1xx ... made it work with RBBS v17
  9. '*  v2.2 ..... fixed some inconsistincies in the code as to # of lines in msg.
  10. '*             Some of the code thought 99 was length, some thought 100.
  11. '*  v2.3 ..... let it work with quoted reply.  No more REDIM of ZOutTxt$
  12. '*  v2.4 ..... removed tabs, margins code to be smaller
  13. '*  v2.41..... fixed bug with loss of bold attribute occasionally
  14. '*  v2.42..... made it work as a v17.3 subroutine.  Added block delete.
  15. '*  v2.43..... Added to: and from:.  Made cursor keys work locally.
  16. '*  v2.43a.... Stupid little bugs fixed
  17. '*  v2.44..... Fixed bugs, added ^T, Import, Subject, ASM functions
  18. '*  v2.44a.... Wordwrap/reflow bug fixed.  Arrows work in del.  Lines renum.
  19. '*
  20. '*  Returns:
  21. '*  ZSubParm  =  1 - Save Message
  22. '*            =  2 - Abort Message
  23. '*            = -1 - Dropped Carrier
  24. '*            = -2 - Sleep Disconnect
  25. '*
  26. '* Run with:
  27. '*   QB C:\RBBSARCS\AED244.BAS /LANSIED.QLB
  28. '*
  29.  
  30. DECLARE SUB Ansied (T$, S$, L%)
  31. DECLARE SUB BackspChar ()
  32. DECLARE SUB CarrRetKey ()
  33. DECLARE SUB ChangeSubject ()
  34. DECLARE SUB ClearScreen ()
  35. DECLARE SUB DeleteCurrentLine (Index%)
  36. DECLARE SUB DisplayMainMenu ()
  37. DECLARE SUB DoneWithMsg (YY$)
  38. DECLARE SUB EraseToEOL (LineNumber%, ColNumber%)
  39. DECLARE SUB MenuCommand (YY$)
  40. DECLARE SUB FindEndOfMsg (EndOfMsg%)
  41. DECLARE SUB FindWord (YY$, I%, NewCol%)
  42. DECLARE SUB FindWrap (YY$, WhereToWrap%)
  43. DECLARE SUB GetChar (YY$)
  44. DECLARE SUB GetString (Prompt$, YY$)
  45. DECLARE SUB HelpMe ()
  46. DECLARE SUB ImportFile ()
  47. DECLARE SUB LastParaLine (I%, LastLine%, Result%)
  48. DECLARE SUB MoveCurStr (CurrentRow%, CurrentCol%, NewRow%, NewCol%, YY$, YLen%)
  49. DECLARE SUB MoveCursor (NewRow%, NewCol%)
  50. DECLARE SUB NormalChar (YY$)
  51. DECLARE SUB PutScreen (YY$, Colour%, Bold%)
  52. DECLARE SUB ReformText (Justify%)
  53. DECLARE SUB SaveCursor (Row%, Col%)
  54. DECLARE SUB UnString (YY$, BadString$)
  55. DECLARE SUB UnGetChar (X%)
  56. DECLARE SUB UpdateScreen ()
  57. DECLARE SUB UpdateStatusLine (How%)
  58.  
  59. DECLARE SUB BufFile (FileName$, Z%)
  60. DECLARE SUB Carrier ()
  61. DECLARE SUB CheckTime (LogoffTime!, Remain!, Z%)
  62. DECLARE SUB ColorPrompt (YY$)
  63. DECLARE SUB EofComm (Char%)
  64. DECLARE SUB FindFKey ()
  65. DECLARE SUB FindIt (FileName$)
  66. DECLARE SUB GetCom (YY$)
  67. DECLARE SUB Line25 ()
  68. DECLARE SUB MsgImport (MaxLines%, MaxLen%, NumLines%, LineAra$())
  69. DECLARE SUB NameCaps (YY$)
  70. DECLARE SUB QuickTput (YY$, NumReturns%)
  71. DECLARE SUB Tput ()
  72. DECLARE SUB TrimTrail (YY$, XX$)
  73. DECLARE SUB UpdtCalr (YY$, Z%)
  74.  
  75. ' $INCLUDE: 'RBBS-VAR.MOD'
  76.  
  77. 100   CONST RedFore = 31
  78.       CONST GreenFore = 32
  79.       CONST YellowFore = 33
  80.       CONST BlueFore = 34
  81.       CONST MagentaFore = 35
  82.       CONST CyanFore = 36
  83.       CONST WhiteFore = 37
  84.       CONST BlueBack = 44
  85.       CONST DefaultColor = 99
  86.       CONST DefaultBold = 99
  87.  
  88. 110   CONST ESCKey = 27
  89.       CONST BackspKey = 8
  90.       CONST OtherBackspKey = 127
  91.       CONST CarrRet = 13
  92.       CONST WordLeftKey = 1          ' Ctrl-A
  93.       CONST ReformTextKey = 2        ' Ctrl-B
  94.       CONST PageDownKey = 3          ' Ctrl-C
  95.       CONST ColRightKey = 4          ' Ctrl-D
  96.       CONST LineUpKey = 5            ' Ctrl-E
  97.       CONST WordRightKey = 6         ' Ctrl-F
  98.       CONST CharDeleteKey = 7        ' Ctrl-G
  99.       CONST EndSessionKey = 11       ' Ctrl-K
  100.       CONST HelpKey = 14             ' Ctrl-N
  101.       CONST ReflowTextKey = 15       ' Ctrl-O
  102.       CONST RepaintKey = 16          ' Ctrl-P
  103.       CONST PageUpKey = 18           ' Ctrl-R
  104.       CONST ColLeftKey = 19          ' Ctrl-S
  105.       CONST DeleteWordRightKey = 20  ' Ctrl-T
  106.       CONST ToggleINSKey = 22        ' Ctrl-V
  107.       CONST HomeKey = 23             ' Ctrl-W
  108.       CONST LineDownKey = 24         ' Ctrl-X
  109.       CONST LineDeleteKey = 25       ' Ctrl-Y
  110.       CONST EndKey = 26              ' Ctrl-Z
  111.  
  112.       CONST BlankLine$ = ""
  113. 119   CONST Version$ = "v2.44a"      ' v2.44a
  114.  
  115.       DEFINT A-Z
  116.  
  117. 120   COMMON SHARED /Ansied/ CurrentRow, CurrentCol, TopLine
  118.       COMMON SHARED /Ansied/ OldColour, IsBold, InsertMode
  119.       COMMON SHARED /Ansied/ SoftSpace$
  120.       COMMON SHARED /Ansied/ BlockDelActive, MsgLockLines
  121.       COMMON SHARED /Ansied/ BlockLine1, BlockLine2
  122.       COMMON SHARED /Ansied/ MsgTo$, MsgSubj$
  123.  
  124.       '*
  125.       '* Standalone Main Program
  126.       '*
  127.       DIM ZOutTxt$(100)
  128.       DIM ZUserIn$(10)
  129.  
  130.       ZFalse = 0
  131.       ZTrue = NOT ZFalse
  132.       ZEmphasizeOff$ = ""
  133.       ZLocalUser = ZTrue
  134.       ZLinesInMsg = 56
  135.       ZRightMargin = 76
  136.       ZMaxMsgLines = 60
  137.       FOR I = 4 TO ZLinesInMsg
  138.          ZOutTxt$(I) = "> This is line number" + STR$(I)
  139.       NEXT
  140.       ZOutTxt$(1) = "* Locked Message Line 1 *"
  141.       ZOutTxt$(2) = "* Locked Message Line 2 *"
  142.       CALL Ansied("Mike Zakharoff", "(R)New Fullscreen Editor", 2)
  143.       END
  144.  
  145. '*  AnsiEd
  146. '*----------------------------------------------------------------------------
  147. '*  Main full-screen editor routine
  148. '*
  149. '*
  150.       SUB Ansied (T$, S$, L%)
  151.  
  152.       '*
  153.       '* ZworkAra$() holds what's currently on the user's screen.
  154.       '* 24 Lines: ZWorkAra$(1) = Menu, Bottom Line = "Line 25"
  155.       '*
  156. 500   REDIM ZWorkAra$(24)
  157.       '*
  158.       '* TopLine is the index into the ZOutTxt$() array that
  159.       '* corresponds to the top of the displayed image, i.e.
  160.       '* what's on line 3 of the user's screen.
  161.       '*
  162.       '*   1,12,23,34,45,56,78
  163.       '*
  164.       TopLine = 1
  165.       SoftSpace$ = CHR$(250)
  166.       InsertMode = ZTrue
  167.       ZLineFeed$ = CHR$(10)
  168.       BlockDelActive = ZFalse
  169.       HiLiteSave = ZHiLiteOff
  170.       ZHiLiteOff = ZFalse
  171.       UseTputSave = ZUseTput
  172.       ZUseTput = ZFalse
  173.  
  174.       MsgLockLines = L
  175.  
  176.       MsgTo$ = T$
  177.       CALL NameCaps(MsgTo$)
  178.  
  179.       MsgSubj$ = S$
  180.       YY$ = ""
  181.       IF LEFT$(MsgSubj$, 3) = "(R)" THEN
  182.          YY$ = "(R)"
  183.          MsgSubj$ = MID$(MsgSubj$, 4)
  184.       END IF
  185.       CALL NameCaps(MsgSubj$)
  186.       MsgSubj$ = YY$ + MsgSubj$
  187.  
  188.       '*
  189.       '* Initialize the screen
  190.       '*
  191. 510   CALL ClearScreen
  192.       CALL UpdateStatusLine(1)
  193.       CALL MoveCursor(3, 1)
  194.       '*
  195.       '* Remove ANSI sequences from the quoted lines
  196.       '*
  197.       IF ZLinesInMsg > 88 THEN
  198.          ZLinesInMsg = 88
  199.       END IF
  200.       IF ZMaxMsgLines > 98 THEN
  201.          ZMaxMsgLines = 98
  202.       END IF
  203.       IF ZLinesInMsg > ZMaxMsgLines THEN
  204.          ZLinesInMsg = ZMaxMsgLines
  205.       END IF
  206.       FOR I = ZLinesInMsg + 1 TO 99
  207.          ZOutTxt$(I) = BlankLine$
  208.       NEXT
  209.       IF ZLinesInMsg <> 0 THEN
  210.          FOR I = 1 TO ZLinesInMsg
  211.             CALL UnString(ZOutTxt$(I), "")
  212.          NEXT
  213.          J = ZLinesInMsg \ 11
  214.          IF ZLinesInMsg MOD 11 = 0 THEN
  215.            J = J - 1
  216.          END IF
  217.          TopLine = J * 11 + 1
  218.          J = ZLinesInMsg - TopLine
  219.          CALL MoveCursor(J + 5, 1)
  220.       END IF
  221.       CALL UpdateScreen
  222.  
  223.       '*
  224.       '* Run the Editor
  225.       '*
  226. 520   WHILE 1
  227.  
  228.          CALL GetChar(B$): GOSUB 740
  229.          KeyPressed = ASC(B$)
  230.          CALL SaveCursor(RowSave, ColSave)
  231.  
  232.          '*
  233.          '* Look for an ANSI escape sequence after an ESC
  234.          '*
  235. 525      IF KeyPressed = ESCKey THEN            ' v2.44a
  236.             CALL GetChar(B$): GOSUB 740
  237.             IF B$ = "[" THEN                    ' ANSI sequence
  238.                CALL GetChar(B$): GOSUB 740
  239.                IF B$ = "C" THEN
  240.                   KeyPressed = ColRightKey
  241.                ELSEIF B$ = "D" THEN
  242.                   KeyPressed = ColLeftKey
  243.                ELSEIF B$ = "A" THEN
  244.                   KeyPressed = LineUpKey
  245.                ELSEIF B$ = "B" THEN
  246.                   KeyPressed = LineDownKey
  247.                END IF
  248.             END IF
  249.          END IF
  250.  
  251.          Index = CurrentRow + TopLine - 3
  252.  
  253.          IF BlockDelActive OR Index <= MsgLockLines OR Index > ZMaxMsgLines THEN
  254. 530         SELECT CASE KeyPressed
  255.                CASE CarrRet
  256.                   IF BlockDelActive THEN
  257.                      BlockDelActive = ZFalse
  258.                      BlockLine2 = Index
  259.                      IF BlockLine2 < BlockLine1 THEN
  260.                         SWAP BlockLine1, BlockLine2
  261.                      END IF
  262.                      IF BlockLine1 <= MsgLockLines THEN
  263.                         BlockLine1 = MsgLockLines + 1
  264.                      END IF
  265.                      IF BlockLine2 > ZMaxMsgLines THEN
  266.                         BlockLine2 = ZMaxMsgLines
  267.                      END IF
  268.                      K = 0
  269.                      FOR I = BlockLine2 + 1 TO 99
  270.                         ZOutTxt$(BlockLine1 + K) = ZOutTxt$(I)
  271.                         K = K + 1
  272.                      NEXT I
  273.                      WHILE BlockLine1 + K <= 99
  274.                         ZOutTxt$(BlockLine1 + K) = BlankLine$
  275.                         K = K + 1
  276.                      WEND
  277.                      CALL UpdateScreen
  278.                      CALL UpdateStatusLine(2)
  279.                      CALL MoveCursor(BlockRow, BlockCol)
  280.                   END IF
  281.                   KeyPressed = 255
  282.  
  283. 540            CASE ESCKey
  284.                   IF BlockDelActive THEN
  285.                      BlockDelActive = ZFalse
  286.                      CALL UpdateStatusLine(2)
  287.                      CALL MoveCursor(BlockRow, BlockCol)
  288.                      KeyPressed = 255
  289.                   END IF
  290.  
  291.                CASE LineUpKey, LineDownKey, PageDownKey, PageUpKey
  292.                   '*
  293.                   '* Up and Down get passed on
  294.                   '*
  295.                CASE ELSE
  296.                   '*
  297.                   '* Ignore the key
  298.                   '*
  299.                   KeyPressed = 255
  300.  
  301.             END SELECT
  302.          END IF
  303.  
  304. 560      SELECT CASE KeyPressed
  305.             CASE ESCKey, EndSessionKey
  306.                '*
  307.                '* User wants to see main menu
  308.                '*
  309.                CALL DisplayMainMenu
  310.                CALL MoveCursor(RowSave, ColSave)
  311.                CALL GetChar(B$): GOSUB 740
  312.                B$ = UCASE$(B$)
  313.                IF B$ = "D" THEN
  314.                   BlockDelActive = ZTrue
  315.                   BlockLine1 = RowSave + TopLine - 3
  316.                   BlockCol = ColSave
  317.                   BlockRow = RowSave
  318.                   CALL EraseToEOL(1, 1)
  319.                   ' v2.44a
  320.                   CALL PutScreen("Delete Block: Press ENTER on Last Line to Delete, or ESC Twice to Quit", DefaultColor, DefaultBold)
  321.                   BlockLine2 = 0
  322.                ELSE
  323.                   CALL MenuCommand(B$): GOSUB 740
  324.                END IF
  325.                CALL MoveCursor(RowSave, ColSave)
  326.  
  327. 570         CASE LineUpKey
  328.                '*
  329.                '* Move the current cursor position up one line
  330.                '*
  331.                IF CurrentRow > 3 THEN
  332.                   CALL MoveCursor(CurrentRow - 1, CurrentCol)
  333.                ELSE
  334.                   IF TopLine <> 1 THEN
  335.                      TopLine = TopLine - 11
  336.                      CALL MoveCursor(CurrentRow + 10, CurrentCol)
  337.                      CALL UpdateScreen
  338.                   END IF
  339.                END IF
  340.  
  341. 580         CASE LineDownKey
  342.                '*
  343.                '* Move the current cursor position down one line
  344.                '*
  345.                IF CurrentRow < 24 THEN
  346.                   CALL MoveCursor(CurrentRow + 1, CurrentCol)
  347.                ELSE
  348.                   IF NOT TopLine = 78 THEN
  349.                      TopLine = TopLine + 11
  350.                      CALL MoveCursor(CurrentRow - 10, CurrentCol)
  351.                      CALL UpdateScreen
  352.                   END IF
  353.                END IF
  354.  
  355. 590         CASE ColLeftKey
  356.                '*
  357.                '* Move the current cursor left one column
  358.                '*
  359.                IF CurrentCol > 1 THEN
  360.                   CALL MoveCursor(CurrentRow, CurrentCol - 1)
  361.                END IF
  362.  
  363. 600         CASE ColRightKey
  364.                '*
  365.                '* Move the current cursor right one column
  366.                '*
  367.                IF CurrentCol < 79 THEN
  368.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  369.                END IF
  370.  
  371. 610         CASE WordRightKey, WordLeftKey
  372.                '*
  373.                '* Move the current cursor one word
  374.                '*
  375.                I = KeyPressed - WordLeftKey
  376.                NewCol = CurrentCol
  377.                CALL FindWord(ZOutTxt$(Index), I, NewCol)
  378.                IF NewCol > 79 THEN
  379.                   NewCol = 79
  380.                END IF
  381.                CALL MoveCursor(CurrentRow, NewCol)
  382.  
  383. 620         CASE DeleteWordRightKey
  384.                '*
  385.                '* Delete the current word
  386.                '*
  387.                I = CurrentCol
  388.                L = LEN(ZOutTxt$(Index))
  389.                CALL FindWord(ZOutTxt$(Index), 1, I)
  390.                IF I > CurrentCol THEN
  391.                   YY$ = MID$(ZOutTxt$(Index), I)
  392.                   MID$(ZOutTxt$(Index), CurrentCol) = YY$
  393.                   ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), L - (I - CurrentCol))
  394.                   CALL PutScreen(YY$, YellowFore, ZTrue)
  395.                   CALL EraseToEOL(RowSave, CurrentCol)
  396.                   CALL MoveCursor(RowSave, ColSave)
  397.                END IF
  398.  
  399. 630         CASE HomeKey
  400.                '*
  401.                '* Move cursor to the start of the line
  402.                '*
  403.                CALL MoveCursor(CurrentRow, 1)
  404.  
  405. 640         CASE EndKey
  406.                '*
  407.                '* Move cursor to the end of the line
  408.                '*
  409.                NewCol = LEN(ZOutTxt$(Index)) + 1
  410.                IF NewCol > 79 THEN
  411.                   NewCol = 79
  412.                END IF
  413.                CALL MoveCursor(CurrentRow, NewCol)
  414.  
  415. 650         CASE PageDownKey
  416.                '*
  417.                '* Move the display one page down
  418.                '*
  419.                TopLine = TopLine + 22
  420.                IF TopLine > 78 THEN
  421.                   TopLine = 78
  422.                END IF
  423.                CALL UpdateScreen
  424.  
  425. 660         CASE PageUpKey
  426.                '*
  427.                '* Move the display one page up
  428.                '*
  429.                TopLine = TopLine - 22
  430.                IF TopLine < 1 THEN
  431.                   TopLine = 1
  432.                END IF
  433.                CALL UpdateScreen
  434.  
  435. 670         CASE LineDeleteKey
  436.                '*
  437.                '* Delete the current line in the file
  438.                '*
  439.                CALL DeleteCurrentLine(Index)
  440.                CALL MoveCursor(RowSave, ColSave)
  441.  
  442. 680         CASE CharDeleteKey
  443.                '*
  444.                '* Delete the current character
  445.                '*
  446.                IF CurrentCol <= LEN(ZOutTxt$(Index)) THEN
  447.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  448.                   CALL BackspChar
  449.                END IF
  450.  
  451. 690         CASE BackspKey, OtherBackspKey
  452.                '*
  453.                '* Back up one character and destroy it
  454.                '*
  455.                CALL BackspChar
  456.  
  457. 700         CASE CarrRet
  458.                '*
  459.                '* Move to the next line, left column
  460.                '*
  461.                IF NOT Index >= ZMaxMsgLines THEN
  462.                   CALL CarrRetKey
  463.                END IF
  464.  
  465. 710         CASE HelpKey, ReformTextKey, ReflowTextKey, ToggleINSKey, RepaintKey
  466.                '*
  467.                '* Execute a main menu command
  468.                '*
  469.                '*          1234567890123456789012
  470.                YY$ = MID$(" J           HRP     I", KeyPressed, 1)
  471.                CALL MenuCommand(YY$): GOSUB 740
  472.                CALL MoveCursor(RowSave, ColSave)
  473.  
  474.             CASE IS > 127, IS < 32
  475.                '*
  476.                '* Ignore characters above 127 or below 32
  477.                '*
  478. 720         CASE ELSE
  479.                '*
  480.                '* Input was a normal character
  481.                '*
  482.                CALL NormalChar(B$)
  483.  
  484.          END SELECT
  485.       WEND
  486.  
  487. 730   REDIM ZWorkAra$(13)
  488.       ZHiLiteOff = HiLiteSave
  489.       ZUseTput = UseTputSave
  490.       S$ = UCASE$(MsgSubj$)
  491.       EXIT SUB
  492.  
  493.       '*
  494.       '* Test ZSubParm and Exit ANSIED if the carrier dropped
  495.       '*
  496. 740   IF ZSubParm <> 0 THEN
  497.          GOTO 730
  498.       END IF
  499.       RETURN
  500.  
  501.       END SUB         ' Sub AnsiEd
  502.  
  503. '*  BackspChar()
  504. '*----------------------------------------------------------------------------
  505. '*  This routine handles the user entering the backspace key
  506. '*
  507. '*
  508.       SUB BackspChar
  509. 1200  CALL SaveCursor(RowSave, ColSave)
  510.       Index = TopLine + CurrentRow - 3
  511.       IF Index = MsgLockLines + 1 AND CurrentCol = 1 THEN
  512.          EXIT SUB
  513.       END IF
  514.       AtEndOfLine = CurrentCol > LEN(ZOutTxt$(Index))
  515. 1210  IF CurrentCol > 1 THEN
  516.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 2) + MID$(ZOutTxt$(Index), CurrentCol)
  517.          CALL EraseToEOL(CurrentRow, CurrentCol - 1)
  518.          IF NOT AtEndOfLine THEN
  519.             YY$ = MID$(ZOutTxt$(Index), ColSave - 1)
  520.             CALL MoveCursor(RowSave, ColSave - 1)
  521.             CALL PutScreen(YY$, YellowFore, ZTrue)
  522.          END IF
  523.          CALL MoveCursor(RowSave, ColSave - 1)
  524.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  525.       ELSEIF LEN(ZOutTxt$(Index - 1)) >= ZRightMargin THEN
  526.          '*
  527.          '* Do nothing
  528.          '*
  529. 1220  ELSE
  530.          NewCol = LEN(ZOutTxt$(Index - 1)) + 1
  531.          YY$ = ZOutTxt$(Index)
  532.          CALL UnString(YY$, SoftSpace$)
  533.          ZOutTxt$(Index - 1) = ZOutTxt$(Index - 1) + YY$
  534.                                    ' v2.44a
  535.          IF LEN(ZOutTxt$(Index - 1)) <= ZRightMargin THEN
  536.             CALL DeleteCurrentLine(Index)
  537. 1230     ELSE
  538.             CALL FindWrap(LEFT$(ZOutTxt$(Index - 1), ZRightMargin + 1), I)
  539.             IF I <= 1 THEN
  540.                I = ZRightMargin
  541.             END IF
  542.             ZOutTxt$(Index) = MID$(ZOutTxt$(Index - 1), I + 1)
  543.             ZOutTxt$(Index - 1) = LEFT$(ZOutTxt$(Index - 1), I)
  544.          END IF
  545.          IF RowSave > 3 THEN
  546.             CALL MoveCursor(RowSave - 1, NewCol)
  547.             CALL UpdateScreen
  548.          ELSE
  549.             CALL MoveCursor(RowSave, NewCol)
  550.             CALL UnGetChar(LineUpKey)
  551.          END IF
  552.       END IF
  553.       END SUB
  554.  
  555.       SUB BufFile (FileName$, Z)
  556.       END SUB
  557.  
  558.       SUB Carrier
  559.       ZSubParm = 0
  560.       END SUB
  561.  
  562. '*  CarrRetKey()
  563. '*----------------------------------------------------------------------------
  564. '*  This routine handles carriage returns entered in the file
  565. '*
  566. '*
  567.       SUB CarrRetKey
  568. 1300  Index = CurrentRow + TopLine - 3
  569.       IF Index >= 99 THEN
  570.          EXIT SUB
  571.       END IF
  572.       IF InsertMode THEN         ' Insert a new line
  573.          FOR I = 98 TO Index + 1 STEP -1
  574.             ZOutTxt$(I + 1) = ZOutTxt$(I)
  575.          NEXT I
  576.          IF LEN(ZOutTxt$(Index)) >= CurrentCol THEN
  577.             ZOutTxt$(Index + 1) = MID$(ZOutTxt$(Index), CurrentCol)
  578.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1)
  579.          ELSE
  580.             ZOutTxt$(Index + 1) = BlankLine$
  581.          END IF
  582.          CALL UpdateScreen
  583.       END IF
  584.       IF CurrentRow < 24 THEN
  585.          CALL MoveCursor(CurrentRow + 1, 1)
  586.       ELSE
  587.          CALL MoveCursor(CurrentRow, 1)
  588.          CALL UnGetChar(LineDownKey)
  589.       END IF
  590.       END SUB
  591.  
  592. '*  ChangeSubject()
  593. '*----------------------------------------------------------------------------
  594. '*  Routine to allow user to change the message subject
  595. '*
  596. '*
  597.       SUB ChangeSubject
  598.       CALL GetString("Change Subject From '" + MsgSubj$ + "' To? ", NewSubj$)
  599.       IF NewSubj$ <> "" THEN
  600.          MsgSubj$ = LEFT$(NewSubj$, 25)
  601.          CALL NameCaps(MsgSubj$)
  602.       END IF
  603.       END SUB
  604.  
  605.       SUB CheckTime (LogoffTime!, Remain!, Z)
  606.       Remain! = 1
  607.       END SUB
  608.  
  609. '*  ClearScreen()
  610. '*----------------------------------------------------------------------------
  611. '*  This routine clears the screen and moves the cursor to row 2, col 1
  612. '*
  613. '*
  614.       SUB ClearScreen
  615. 1500  FOR I = 1 TO 23
  616.          ZWorkAra$(I) = BlankLine$
  617.       NEXT I
  618.       CALL QuickTput("", 0)
  619.       ZSubParm = 2
  620.       CALL Line25
  621.       ZSubParm = 0
  622.       CALL QuickTput("H" + ZEmphasizeOff$, 0)
  623.       CurrentCol = 1
  624.       CurrentRow = 3
  625.       IsBold = DefaultBold
  626.       OldColour = DefaultColor
  627.       END SUB
  628.  
  629.       SUB ColorPrompt (YY$)
  630.       CALL QuickTput(ZEmphasizeOff$, 0)
  631.       END SUB
  632.  
  633. '*  DeleteCurrentLine()
  634. '*----------------------------------------------------------------------------
  635. '*  This routine deletes the current line on the screen and in the array
  636. '*  ZOutTxt$, and moves the next lower line up one  It then repaints the
  637. '*  affected portion of the screen (from the deleted line down)
  638. '*
  639. '*
  640.       SUB DeleteCurrentLine (Index%)
  641. 1600  FOR I = Index% TO 98
  642.          ZOutTxt$(I) = ZOutTxt$(I + 1)
  643.       NEXT I
  644.       ZOutTxt$(99) = BlankLine$
  645.       CALL UpdateScreen
  646.       END SUB
  647.  
  648. '*  DisplayMainMenu()
  649. '*----------------------------------------------------------------------------
  650. '*  This routine displays the main menu on the top line
  651. '*
  652. '*
  653.       SUB DisplayMainMenu
  654. 1700  CALL MoveCursor(1, 1)
  655.       YY$ = "A)bort H)elp D)elete I)ns/ovw J)ustify "
  656.       IF ZLocalUser OR ZSysop THEN
  657.          YY$ = YY$ + "O)import R)eflow P)aint S)ave U)subject "
  658.       ELSE
  659.          YY$ = YY$ + "R)eflow P)aint S)ave U)subject          "
  660.       END IF
  661.       CALL ColorPrompt(YY$)
  662.       CALL PutScreen(YY$, DefaultColor, DefaultBold)
  663.       END SUB
  664.  
  665. '*  DoneWithMsg()
  666. '*----------------------------------------------------------------------------
  667. '*  This routine is called to save or abort the message
  668. '*
  669. '*
  670.       SUB DoneWithMsg (YY$)
  671. 1810  SELECT CASE YY$
  672.          CASE "S"        ' Save Message
  673.             '*
  674.             '* Remove trailing blank lines from the message
  675.             '*
  676.             CALL FindEndOfMsg(EndOfMsg)
  677.             FOR I = 1 TO EndOfMsg
  678.                J = INSTR(ZOutTxt$(I), SoftSpace$)
  679.                WHILE J <> 0
  680.                   MID$(ZOutTxt$(I), J, 1) = " "
  681.                   J = INSTR(ZOutTxt$(I), SoftSpace$)
  682.                WEND
  683.                CALL TrimTrail(ZOutTxt$(I), " ")
  684.             NEXT I
  685.             CALL FindEndOfMsg(ZLinesInMsg)
  686.             CALL ClearScreen
  687.             ZSubParm = 1
  688.  
  689. 1820     CASE "A"
  690.             CALL EraseToEOL(1, 1)
  691.             YY$ = "Abort: Are You Sure (Y)es,[N]o)? "
  692.             CALL ColorPrompt(YY$)
  693.             CALL PutScreen(YY$, DefaultColor, DefaultBold)
  694.             CALL GetChar(B$)
  695.             IF ZSubParm <> 0 THEN
  696.                B$ = "Y"
  697.             END IF
  698.             IF UCASE$(B$) = "Y" THEN
  699.                CALL ClearScreen
  700.                ZSubParm = 2
  701.             END IF
  702.       END SELECT
  703.       END SUB
  704.  
  705.       SUB EofComm (Char%)
  706.       Char% = -1
  707.       END SUB
  708.  
  709. '*  EraseToEOL()
  710. '*----------------------------------------------------------------------------
  711. '*  This routine clears from a position to to the end of that line
  712. '*
  713. '*
  714.       SUB EraseToEOL (LineNumber, ColNumber)
  715. 1900  CALL MoveCursor(LineNumber, ColNumber)
  716.       CALL QuickTput("", 0)
  717.       END SUB
  718.  
  719. '*  FindEndOfMsg()
  720. '*----------------------------------------------------------------------------
  721. '*  Finds the last active line in the message
  722. '*
  723. '*
  724.       SUB FindEndOfMsg (EndOfMsg)
  725.       EndOfMsg = 1
  726.       FOR I = ZMaxMsgLines TO 1 STEP -1
  727.          IF ZOutTxt$(I) <> BlankLine$ OR I <= MsgLockLines THEN
  728.             EndOfMsg = I
  729.             EXIT FOR
  730.          END IF
  731.       NEXT I
  732.       END SUB
  733.  
  734.       SUB FindFKey
  735.       ZSubParm = 0
  736.       ZKeyPressed$ = ""
  737.       END SUB
  738.  
  739.       SUB FindIt (FileName$)
  740.       ZOK = ZTrue
  741.       END SUB
  742.  
  743. '*  FindWrap()
  744. '*----------------------------------------------------------------------------
  745. '*  This routine finds a place in the string yy$ that could be used as a
  746. '*  place to wrap the line WhereToWrap should be the last position that
  747. '*  remains in the line, ie
  748. '*    set   currentline$ = left$(yy$,wheretowrap)
  749. '*          nextline$    = mid$ (yy$,wheretowrap+1)
  750. '*
  751. '*
  752.       SUB FindWrap (YY$, WhereToWrap)
  753. 2100  WhereToWrap = LEN(YY$) + 1
  754.       CALL FindWord(YY$, 0, WhereToWrap)
  755.       WhereToWrap = WhereToWrap - 1
  756.       END SUB
  757.  
  758. '*  GetChar()
  759. '*----------------------------------------------------------------------------
  760. '*  This routine reads a character from the user into YY$
  761. '*
  762. '*
  763.       SUB GetChar (YY$)
  764. 2200  ZAutoLogoff! = TIMER + ZWaitBeforeDisconnect
  765.       CALL Carrier
  766.       YY$ = ""
  767.       WHILE ZSubParm <> -1 AND ZSubParm <> -2 AND YY$ = ""
  768.          ZSubParm = 0
  769.          IF LEN(ZCommportStack$) > 0 THEN
  770.             YY$ = LEFT$(ZCommportStack$, 1)
  771.             ZCommportStack$ = MID$(ZCommportStack$, 2)
  772.          ELSE
  773.             IF ZLocalUser THEN
  774.                YY$ = INKEY$
  775.                IF LEN(YY$) = 2 THEN
  776.                   KeyPressed = ASC(RIGHT$(YY$, 1))
  777.                   YY$ = ""
  778.                   SELECT CASE KeyPressed
  779.                      CASE 82                  ' Insert
  780.                         KeyPressed = ToggleINSKey
  781.                      CASE 83                  ' Delete
  782.                         KeyPressed = CharDeleteKey
  783.                      CASE 71                  ' Home
  784.                         KeyPressed = HomeKey
  785.                      CASE 73                  ' PgUp
  786.                         KeyPressed = PageUpKey
  787.                      CASE 72                  ' Up Arrow
  788.                         KeyPressed = LineUpKey
  789.                      CASE 80                  ' Down Arrow
  790.                         KeyPressed = LineDownKey
  791.                      CASE 81                  ' PgDn
  792.                         KeyPressed = PageDownKey
  793.                      CASE 75                  ' Left Arrow
  794.                         KeyPressed = ColLeftKey
  795.                      CASE 77                  ' Right Arrow
  796.                         KeyPressed = ColRightKey
  797.                      CASE 115                 ' Ctrl-Left Arrow
  798.                         KeyPressed = WordLeftKey
  799.                      CASE 116                 ' Ctrl-Right Arrow
  800.                         KeyPressed = WordRightKey
  801.                      CASE 79                  ' End
  802.                         KeyPressed = EndKey
  803.                      CASE ELSE
  804.                         KeyPressed = 0
  805.                   END SELECT
  806.                   IF KeyPressed <> 0 THEN
  807.                      YY$ = CHR$(KeyPressed)
  808.                   END IF
  809.                END IF
  810.             ELSE
  811.                CALL FindFKey
  812.                IF ZSubParm >= 0 THEN
  813.                   YY$ = ZKeyPressed$
  814.                   IF YY$ = "" THEN
  815.                      CALL EofComm(Char%)
  816.                      IF Char% = -1 THEN
  817.                         CALL CheckTime(ZAutoLogoff!, Remain!, 1)
  818.                         IF Remain! < 0 THEN
  819.                            CALL UpdtCalr("Sleep disconnect", 1)
  820.                            ZSubParm = -2
  821.                            ZNo = ZTrue
  822.                            ZSleepDisconnect = ZTrue
  823.                         END IF
  824.                      ELSE
  825.                         CALL Carrier
  826.                         IF ZSubParm <> -1 THEN
  827.                            ZSubParm = 0
  828.                            CALL GetCom(YY$)
  829.                         END IF
  830.                      END IF
  831.                   END IF
  832.                END IF
  833.             END IF
  834.          END IF
  835.       WEND
  836.       END SUB
  837.  
  838.       SUB GetCom (YY$)
  839.       END SUB
  840.  
  841. '*  GetString()
  842. '*----------------------------------------------------------------------------
  843. '*  Gets a string from the user
  844. '*
  845. '*
  846.       SUB GetString (Prompt$, YY$)
  847.       YY$ = ""
  848.       CALL EraseToEOL(1, 1)
  849.       CALL PutScreen(Prompt$, DefaultColor, DefaultBold)
  850.       NewCol = CurrentCol
  851.       InitCol = NewCol
  852.       DO
  853.          CALL MoveCursor(CurrentRow, NewCol)
  854.          CALL GetChar(B$)
  855.          IF ZSubParm <> 0 THEN
  856.             B$ = CHR$(ESCKey)
  857.          END IF
  858.          KeyPressed = ASC(B$)
  859.          SELECT CASE KeyPressed
  860.             CASE BackspKey, OtherBackspKey
  861.                IF NewCol <> InitCol THEN
  862.                   CALL MoveCursor(CurrentRow, NewCol - 1)
  863.                   CALL PutScreen(" ", DefaultColor, DefaultBold)
  864.                   NewCol = NewCol - 1
  865.                   YY$ = LEFT$(YY$, LEN(YY$) - 1)
  866.                END IF
  867.             CASE CarrRet
  868.                EXIT DO
  869.             CASE ESCKey
  870.                YY$ = ""
  871.                EXIT DO
  872.             CASE ELSE
  873.                YY$ = YY$ + B$
  874.                CALL PutScreen(B$, DefaultColor, DefaultBold)
  875.                NewCol = NewCol + 1
  876.          END SELECT
  877.       LOOP WHILE 1
  878.       END SUB
  879.  
  880. '*  HelpMe()
  881. '*----------------------------------------------------------------------------
  882. '*  This routine provides on-line help for the user
  883. '*
  884. '*
  885.       SUB HelpMe
  886. 2300  CALL SaveCursor(RowSave, ColSave)
  887.       CALL ClearScreen
  888.       CALL BufFile(ZHelpPath$ + "ANSIED" + ZHelpExtension$, X)
  889.       CALL ClearScreen
  890.       CALL UpdateScreen
  891.       CALL MoveCursor(RowSave, ColSave)
  892.       END SUB
  893.  
  894. '*  ImportFile()
  895. '*----------------------------------------------------------------------------
  896. '*  Imports an ASCII text file in the message
  897. '*
  898. '*
  899.       SUB ImportFile
  900.       IF ZLocalUser OR ZSysop THEN
  901.          CALL GetString("Import What File? ", FileName$)
  902.          IF FileName$ <> "" THEN
  903.             CALL FindIt(FileName$)
  904.             IF ZOK THEN
  905.                ZUserIn$(1) = FileName$
  906.                ZAnsIndex = 0
  907.                ZLastIndex = 1
  908.                CALL FindEndOfMsg(EndOfMsg)
  909.                CALL MsgImport(ZMaxMsgLines, ZRightMargin, EndOfMsg, ZOutTxt$())
  910.                CALL UpdateScreen
  911.             END IF
  912.          END IF
  913.       END IF
  914.       END SUB
  915.  
  916. '*  LastParaLine()
  917. '*----------------------------------------------------------------------------
  918. '*  This routine returns ZTrue if ZOutTxt$(I) is the last line
  919. '*  in a paragraph
  920. '*
  921. '*
  922.       SUB LastParaLine (I, LastLine, Result)
  923. 2400  Result = ZFalse
  924.       IF I = LastLine OR I >= ZMaxMsgLines THEN
  925.          Result = ZTrue
  926.       ELSE
  927.          YY$ = ZOutTxt$(I)
  928.          J = INSTR(YY$, ">")
  929.          IF J = 0 THEN
  930.             J = 6
  931.          END IF
  932.          IF J < 5 THEN
  933.             Result = ZTrue
  934.          ELSEIF YY$ = BlankLine$ THEN
  935.             Result = ZTrue
  936.          ELSE
  937.             IF ZOutTxt$(I + 1) = BlankLine$ THEN
  938.                Result = ZTrue
  939.             ELSEIF LEFT$(ZOutTxt$(I + 1), 1) = " " THEN
  940.                Result = ZTrue
  941.             ELSE
  942.                K = INSTR(ZOutTxt$(I + 1), ">")
  943.                IF K <> 0 AND K < 5 THEN
  944.                   Result = ZTrue
  945.                END IF
  946.             END IF
  947.          END IF
  948.       END IF
  949.       END SUB
  950.  
  951.       SUB Line25
  952.       END SUB
  953.  
  954. '*  MenuCommand()
  955. '*----------------------------------------------------------------------------
  956. '* This routine executes the passed main menu command
  957. '*
  958. '*
  959.       SUB MenuCommand (YY$)
  960. 2450  ZSubParm = 0              ' v2.44a
  961.       SELECT CASE YY$
  962.          CASE "H"
  963.             CALL HelpMe
  964.          CASE "S", "A"
  965.             CALL DoneWithMsg(YY$)
  966.          CASE "P"
  967.             CALL ClearScreen
  968.             CALL UpdateScreen
  969.          CASE "I"
  970.             InsertMode = NOT InsertMode
  971.          CASE "R"
  972.             CALL ReformText(ZFalse)
  973.          CASE "J"
  974.             CALL ReformText(ZTrue)
  975.          CASE "O"
  976.             CALL ImportFile
  977.          CASE "U"
  978.             CALL ChangeSubject
  979.       END SELECT
  980.       IF ZSubParm = 0 THEN
  981.          CALL EraseToEOL(1, 1)
  982.          CALL UpdateStatusLine(1)
  983.       END IF
  984.       END SUB
  985.  
  986. '*  MoveCursor()
  987. '*----------------------------------------------------------------------------
  988. '*  This routine moves the cursor to the position spec'd by newcol and
  989. '*  newrow and tries to do it with the minimum number of Ansi characters
  990. '*
  991. '*
  992.       SUB MoveCursor (NewRow, NewCol)
  993. 2500  YY$ = "        "
  994.       CALL MoveCurStr(CurrentRow, CurrentCol, NewRow, NewCol, YY$, YLen)
  995.       IF YLen <> 0 THEN
  996.          YY$ = LEFT$(YY$, YLen)
  997.          CALL QuickTput(YY$, 0)
  998.       END IF
  999.       ZSubParm = 0
  1000.       END SUB
  1001.  
  1002.       SUB MsgImport (MaxLines, MaxLen, NumLines, LineAra$())
  1003.       OPEN ZUserIn$(ZAnsIndex + 1) FOR INPUT AS #2
  1004.       NumLines = NumLines + 1
  1005.       WHILE NumLines <= MaxLines AND NOT EOF(2)
  1006.          LINE INPUT #2, LineAra$(NumLines)
  1007.          NumLines = NumLines + 1
  1008.       WEND
  1009.       CLOSE 2
  1010.       END SUB
  1011.  
  1012.       SUB NameCaps (YY$)
  1013.       END SUB
  1014.  
  1015. '*  NormalChar()
  1016. '*----------------------------------------------------------------------------
  1017. '*  This routine handles 'normal' characters entered into the message
  1018. '*
  1019. '*
  1020.       SUB NormalChar (YY$)
  1021.  
  1022. 2600  CALL SaveCursor(RowSave, ColSave)
  1023.       Index = CurrentRow + TopLine - 3
  1024.       CurrentLineBlank = (ZOutTxt$(Index) = BlankLine$)
  1025.       LML = LEN(ZOutTxt$(Index))
  1026.  
  1027.       IF CurrentCol > 79 THEN
  1028.          EXIT SUB
  1029.       END IF
  1030.  
  1031.       AtEndOfLine = ZFalse
  1032.  
  1033.       IF CurrentCol > LML THEN
  1034.          ZOutTxt$(Index) = ZOutTxt$(Index) + SPACE$(CurrentCol - LML)
  1035.          ZWorkAra$(CurrentRow) = ZWorkAra$(CurrentRow) + SPACE$(CurrentCol - LML)
  1036.          LML = LEN(ZOutTxt$(Index))
  1037.          AtEndOfLine = ZTrue
  1038.       END IF
  1039.  
  1040. 2610  IF (CurrentCol <= ZRightMargin AND AtEndOfLine) OR (CurrentCol <= ZRightMargin AND NOT InsertMode) THEN
  1041.          '*
  1042.          '* Single character changed
  1043.          '*
  1044.          MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  1045.          MID$(ZWorkAra$(CurrentRow), CurrentCol, 1) = YY$
  1046.          CALL PutScreen(YY$, YellowFore, ZTrue)
  1047.                                                                                     ' v2.44a
  1048. 2620  ELSEIF (NOT AtEndOfLine AND InsertMode AND CurrentCol <= ZRightMargin AND LML < ZRightMargin) THEN
  1049.          '*
  1050.          '* Have to rewrite the screen from the current pos forward
  1051.          '*
  1052.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  1053.  
  1054.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1055.  
  1056.          CALL EraseToEOL(CurrentRow, CurrentCol)
  1057.          ZZ$ = MID$(ZWorkAra$(CurrentRow), CurrentCol)
  1058.          CALL PutScreen(ZZ$, YellowFore, ZTrue)
  1059.          CALL MoveCursor(RowSave, ColSave + 1)
  1060.  
  1061. 2630  ELSE
  1062.          '*
  1063.          '* Wrap the end of the line
  1064.          '*
  1065.          IF NOT AtEndOfLine THEN
  1066.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  1067.             LML = LML + 1
  1068.          ELSE
  1069.             MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  1070.          END IF
  1071.  
  1072.          CALL FindWrap(ZOutTxt$(Index), I)
  1073.          IF I <= 1 THEN
  1074.             I = ZRightMargin
  1075.          END IF
  1076.  
  1077.          ZZ$ = MID$(ZOutTxt$(Index), (I + 1))
  1078.          CALL TrimTrail(ZZ$, SoftSpace$)
  1079.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), I)
  1080.          '*
  1081.          '* Add to the beginning of a new line
  1082.          '*
  1083.          IF Index <= 98 THEN
  1084.             Index = Index + 1
  1085.          END IF
  1086.  
  1087.          Z = INSTR(ZOutTxt$(Index), ">")                                                  ' v2.44a
  1088.          IF ZOutTxt$(Index) <> BlankLine$ AND (Z <= 0 OR Z > 6) AND LEN(ZOutTxt$(Index)) + LEN(ZZ$) < ZRightMargin THEN
  1089.             ZOutTxt$(Index) = ZZ$ + ZOutTxt$(Index)
  1090.          ELSE
  1091.             FOR J = 98 TO Index STEP -1
  1092.                ZOutTxt$(J + 1) = ZOutTxt$(J)
  1093.             NEXT J
  1094.             ZOutTxt$(Index) = ZZ$
  1095.          END IF
  1096.  
  1097.          CALL EraseToEOL(CurrentRow, I + 1)        ' do the "easy" line
  1098.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1099.  
  1100.          CALL UpdateScreen
  1101.          IF (ColSave > I) THEN
  1102.             NewCol = ColSave - I + 1
  1103.             IF RowSave <> 24 THEN
  1104.                CALL MoveCursor(RowSave + 1, NewCol)
  1105.             ELSE
  1106.                CALL MoveCursor(RowSave, NewCol)
  1107.                CALL UnGetChar(LineDownKey)
  1108.             END IF
  1109.          ELSE
  1110.             CALL MoveCursor(RowSave, ColSave + 1)
  1111.          END IF
  1112.       END IF
  1113.  
  1114.       END SUB
  1115.  
  1116. '*  PutScreen()
  1117. '*----------------------------------------------------------------------------
  1118. '* This routine writes YY$ to the user in the color and
  1119. '* intensity specified
  1120. '*
  1121. '*
  1122.       SUB PutScreen (YY$, Colour, Bold)
  1123. 2800  ZZ$ = ""
  1124.       IF Colour <> 99 THEN
  1125.          IF (Colour <> OldColour) OR (Bold <> IsBold) THEN
  1126.             ZZ$ = ""
  1127.             IF Bold <> IsBold THEN
  1128.                IF Bold THEN
  1129.                   ZZ$ = ZZ$ + "1;"
  1130.                ELSE
  1131.                   ZZ$ = ZZ$ + "0;"
  1132.                END IF
  1133.             END IF
  1134.             ZZ$ = ZZ$ + MID$(STR$(Colour), 2) + "m"
  1135.          END IF
  1136.       ELSE
  1137.          ZZ$ = ZEmphasizeOff$
  1138.       END IF
  1139.       ZOutTxt$ = ZZ$ + YY$
  1140.       IF ZLocalUser THEN
  1141.          CALL QuickTput(ZOutTxt$, 0)
  1142.       ELSE
  1143.          ZSubParm = 4
  1144.          CALL Tput
  1145.       END IF
  1146.       ZSubParm = 0
  1147.       IF INSTR(YY$, "") = 0 THEN
  1148.          CurrentCol = CurrentCol + LEN(YY$)
  1149.          IF CurrentCol > 80 THEN
  1150.             CurrentCol = 0
  1151.             CurrentRow = 0
  1152.          END IF
  1153.       ELSE
  1154.          CurrentRow = 0
  1155.          CurrentCol = 0
  1156.       END IF
  1157.       OldColour = Colour
  1158.       IsBold = Bold
  1159.       END SUB
  1160.  
  1161.       SUB QuickTput (YY$, NumReturns)
  1162.       OPEN "CONS:" FOR OUTPUT AS #3
  1163.       PRINT #3, YY$;
  1164.       FOR I = 1 TO NumReturns
  1165.          PRINT #3,
  1166.       NEXT
  1167.       CLOSE 3
  1168.       END SUB
  1169.  
  1170.       SUB QuickTput1 (YY$)
  1171.       CALL QuickTput(YY$, 1)
  1172.       END SUB
  1173.  
  1174. '*  ReformText()
  1175. '*----------------------------------------------------------------------------
  1176. '*  This routine reflows the text to the current margins.  Optionally,
  1177. '*  it right justifies all lines by adding "soft spaces"
  1178. '*
  1179. '*
  1180.       SUB ReformText (Justify%)
  1181.  
  1182. 2900  DIM Places(80)
  1183.  
  1184.       CALL EraseToEOL(1, 1)
  1185.       CALL PutScreen("Reformatting... Please Wait.", WhiteFore, ZTrue)
  1186.  
  1187.       CALL FindEndOfMsg(EndOfMsg)
  1188.  
  1189.       I = MsgLockLines + 1   ' Read index
  1190.       J = MsgLockLines + 1   ' Write index
  1191.  
  1192.       '*
  1193.       '* Reflow the text to the maximum on a line
  1194.       '*
  1195.       DO WHILE I <= EndOfMsg
  1196.          '*
  1197.          '* Loop until we get a long line or an end of paragraph
  1198.          '*
  1199.          ZOutTxt$ = ""
  1200.          DO WHILE 1
  1201.             YY$ = ZOutTxt$(I)
  1202.             CALL UnString(YY$, SoftSpace$)
  1203.             IF ZOutTxt$ <> "" AND RIGHT$(ZOutTxt$, 1) <> " " THEN
  1204.                ZOutTxt$ = ZOutTxt$ + " "
  1205.             END IF
  1206.             ZOutTxt$ = ZOutTxt$ + YY$
  1207.             CALL LastParaLine(I, EndOfMsg, EndOfPara)
  1208.             I = I + 1
  1209.             IF LEN(ZOutTxt$) > ZRightMargin THEN
  1210.                '*
  1211.                '* Wrap the long line
  1212.                '*
  1213.                CALL FindWrap(LEFT$(ZOutTxt$, ZRightMargin + 1), K)
  1214.                IF K <= 1 THEN
  1215.                   K = ZRightMargin
  1216.                END IF
  1217.                ZOutTxt$(J) = LEFT$(ZOutTxt$, K)
  1218.                IF EndOfPara THEN
  1219.                   '*
  1220.                   '* Go to the next paragraph
  1221.                   '*
  1222.                   J = J + 1
  1223.                   ZOutTxt$(J) = MID$(ZOutTxt$, K + 1)
  1224.                ELSE
  1225.                   '*
  1226.                   '* Keep the remaining part of the line and process
  1227.                   '* it on the next pass
  1228.                   '*
  1229.                   I = I - 1
  1230.                   ZOutTxt$(I) = MID$(ZOutTxt$, K + 1)
  1231.                END IF
  1232.                J = J + 1
  1233.                EXIT DO
  1234.             ELSEIF EndOfPara THEN
  1235.                ZOutTxt$(J) = ZOutTxt$
  1236.                J = J + 1
  1237.                EXIT DO
  1238.             END IF
  1239.          LOOP
  1240.       LOOP
  1241.  
  1242.       FOR I = J TO 99
  1243.          ZOutTxt$(I) = BlankLine$
  1244.       NEXT
  1245.  
  1246.       EndOfMsg = J - 1
  1247.  
  1248.       '*
  1249.       '* Space out the text on each line
  1250.       '*
  1251.       IF Justify% THEN
  1252.          FOR I = MsgLockLines + 1 TO EndOfMsg
  1253.             CALL LastParaLine(I, EndOfMsg, EndOfPara)
  1254.             IF NOT EndOfPara THEN
  1255.                '*
  1256.                '* Space out the line
  1257.                '*
  1258.                ZOutTxt$ = ZOutTxt$(I)
  1259.                CALL TrimTrail(ZOutTxt$, " ")
  1260.                TxtLen = LEN(ZOutTxt$)
  1261.                SpacesToAdd = ZRightMargin - TxtLen
  1262.                IF SpacesToAdd > 0 THEN
  1263.                   '*
  1264.                   '* Skip leading spaces on the line
  1265.                   '*
  1266.                   Place = 1
  1267.                   IF LEFT$(ZOutTxt$, 1) = " " THEN
  1268.                      CALL FindWord(ZOutTxt$, 1, Place)
  1269.                   END IF
  1270.                   '*
  1271.                   '* Find all of the possible places to space out the line
  1272.                   '*
  1273.                   NumPlaces = 0
  1274.                   DO WHILE 1
  1275.                      CALL FindWord(ZOutTxt$, 1, Place)
  1276.                      IF Place < TxtLen THEN
  1277.                         NumPlaces = NumPlaces + 1
  1278.                         Places(NumPlaces) = Place
  1279.                      ELSE
  1280.                         EXIT DO
  1281.                      END IF
  1282.                   LOOP
  1283.                   '*
  1284.                   '* Fill in available places with soft spaces
  1285.                   '*
  1286.                   IF NumPlaces <> 0 THEN
  1287.                      ExtraPlaces = (SpacesToAdd MOD NumPlaces)
  1288.                      LeftExtra = ExtraPlaces \ 2
  1289.                      RightExtra = ExtraPlaces - LeftExtra
  1290.                      FOR J = NumPlaces TO 1 STEP -1
  1291.                         SpacesThisPlace = SpacesToAdd \ NumPlaces
  1292.                         IF J <= LeftExtra OR J > NumPlaces - RightExtra THEN
  1293.                            SpacesThisPlace = SpacesThisPlace + 1
  1294.                         END IF
  1295.                         IF SpacesThisPlace <> 0 THEN
  1296.                            ZOutTxt$ = LEFT$(ZOutTxt$, Places(J) - 1) + STRING$(SpacesThisPlace, SoftSpace$) + MID$(ZOutTxt$, Places(J))
  1297.                         END IF
  1298.                      NEXT J
  1299.                   END IF
  1300.                END IF
  1301.                ZOutTxt$(I) = ZOutTxt$
  1302.             END IF
  1303.          NEXT I
  1304.       END IF
  1305.  
  1306.       CALL UpdateScreen
  1307.  
  1308.       END SUB
  1309.  
  1310. '*  SaveCursor()
  1311. '*----------------------------------------------------------------------------
  1312. '*  This routine saves the current cursor position
  1313. '*
  1314. '*
  1315.       SUB SaveCursor (Row%, Col%)
  1316.       Row% = CurrentRow
  1317.       Col% = CurrentCol
  1318.       END SUB
  1319.  
  1320.       SUB Tput
  1321.       CALL QuickTput(ZOutTxt$, 0)
  1322.       END SUB
  1323.  
  1324.       SUB TrimTrail (YY$, XX$)
  1325.       N = LEN(YY$)
  1326.       WHILE RIGHT$(YY$, 1) = XX$ AND N <> 0
  1327.          YY$ = LEFT$(YY$, N - 1)
  1328.          N = N - 1
  1329.       WEND
  1330.       END SUB
  1331.  
  1332. '*  UnGetChar()
  1333. '*----------------------------------------------------------------------------
  1334. '*   Puts a key in the beginning of the keyboard buffer
  1335. '*
  1336. '*
  1337.       SUB UnGetChar (X)
  1338.       ZCommportStack$ = CHR$(X) + ZCommportStack$
  1339.       END SUB
  1340.  
  1341. '*  UnString()
  1342. '*----------------------------------------------------------------------------
  1343. '*  Removes one string from another
  1344. '*
  1345. '*
  1346.       SUB UnString (YY$, BadString$)
  1347.       I = INSTR(YY$, BadString$)
  1348.       WHILE I <> 0
  1349.          YY$ = LEFT$(YY$, I - 1) + MID$(YY$, I + LEN(BadString$))
  1350.          I = INSTR(YY$, BadString$)
  1351.       WEND
  1352.       END SUB
  1353.  
  1354. '*  UpdateScreen()
  1355. '*----------------------------------------------------------------------------
  1356. '*  This is one of the most important routines  It compares the arrays
  1357. '*  ZOutTxt$ and ZWorkAra$ and only sends the user the DIFFERENCE between the
  1358. '*  two within the viewing area  In this way all processing can be done on
  1359. '*  ZOutTxt$ and then the screen is updated to reflect the changes. After the
  1360. '*  users screen is updated, ZWorkAra$ is changed to reflect what should be
  1361. '*  on the users' screen The cursor is restored to its original position
  1362. '*
  1363. '*
  1364.       SUB UpdateScreen
  1365. 3100  CALL SaveCursor(RowSave, ColSave)
  1366.       FOR I = 3 TO 24
  1367.          Index = I + TopLine - 3
  1368.          ScreenLine$ = ZWorkAra$(I)
  1369.          MessageLine$ = ZOutTxt$(Index)
  1370.          LML = LEN(MessageLine$)
  1371.          IF Index = ZMaxMsgLines + 1 THEN
  1372.             CALL EraseToEOL(I, 1)
  1373.             CALL PutScreen("[* End of Message *]", CyanFore, ZFalse)
  1374.             ZWorkAra$(I) = CHR$(EndKey)
  1375.          ELSEIF Index > ZMaxMsgLines + 1 THEN
  1376.             IF ScreenLine$ <> BlankLine$ THEN
  1377.                CALL EraseToEOL(I, 1)
  1378.                ZWorkAra$(I) = BlankLine$
  1379.             END IF
  1380.          ELSEIF MessageLine$ = ScreenLine$ THEN
  1381.             '*
  1382.             '* Screen = What's in message buffer
  1383.             '*
  1384.          ELSEIF MessageLine$ = BlankLine$ OR MessageLine$ = SPACE$(LML) THEN
  1385.             CALL EraseToEOL(I, 1)
  1386.             ZWorkAra$(I) = MessageLine$
  1387.          ELSE
  1388.             CALL MoveCursor(I, 1)
  1389.             YY$ = MessageLine$
  1390.             CALL PutScreen(YY$, YellowFore, ZTrue)
  1391.             CALL EraseToEOL(CurrentRow, CurrentCol)
  1392.             ZWorkAra$(I) = ZOutTxt$(Index)
  1393.          END IF
  1394.       NEXT I
  1395.       CALL MoveCursor(RowSave, ColSave)
  1396.       END SUB
  1397.  
  1398. '*  UpdateStatusLine()
  1399. '*-----------------------------------------------------------------------------
  1400. '*  Rewrites the status line on screen line(s) 1 and 2
  1401. '*
  1402. '*    Input:  How% = 1   - Rewrite both lines
  1403. '*            How% = 2   - Just rewrite top line
  1404. '*
  1405.       SUB UpdateStatusLine (How%)
  1406. 3200  YY$ = "ANSIED " + Version$ + " by Tom Collins                       * Press ESC Twice for Menu *"
  1407.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  1408.       CALL MoveCursor(1, 1)
  1409.       CALL PutScreen(YY$, BlueFore, ZTrue)
  1410. 3210  IF How% = 1 THEN
  1411.          YY$ = CHR$(205) + " To: " + MsgTo$ + " " + CHR$(205) + " Re: " + MsgSubj$ + " " + CHR$(205)
  1412.          YY$ = YY$ + STRING$(79 - LEN(YY$), CHR$(205))
  1413.          IF InsertMode THEN
  1414.             MID$(YY$, 74) = " Ins "
  1415.          ELSE
  1416.             MID$(YY$, 74) = " Ovw "
  1417.          END IF
  1418.          I = 1
  1419.          CALL MoveCursor(2, I)
  1420.          CALL PutScreen(YY$, WhiteFore, ZFalse)
  1421.       END IF
  1422.       END SUB
  1423.  
  1424.       SUB UpdtCalr (YY$, Z)
  1425.       END SUB
  1426.  
  1427.